package cn.fintecher.pangolin.service.business.service;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.CaseTransferLog;
import cn.fintecher.pangolin.entity.mysql.*;
import cn.fintecher.pangolin.service.business.model.request.*;
import cn.fintecher.pangolin.service.business.model.response.ProcessApplicationResponse;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.BaseCaseRespository;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.CaseTransferLogRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.AssistCaseRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.ProcessApplicationRepository;
import cn.fintecher.pangolin.service.business.repository.jparepository.UserRepository;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author wangxiangdong
 * @Description 流程申请相关业务操作
 * @Date 2019/9/19 11:13
 **/
@Service
@Slf4j
public class CaseApplyManageService {

    @Autowired
    private CaseInfoRepository caseInfoRepository;


    @Autowired
    private FlowConfigurationService flowConfigurationService;

    @Autowired
    private ProcessApplicationRepository processApplicationRepository;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private CaseTransferLogRepository caseTransferLogRepository;

    @Autowired
    private AssistCaseRepository assistCaseRepository;

    @Autowired
    private BaseService baseService;

    @Autowired
    private BaseCaseRespository baseCaseRespository;

    /**
     * @Author wangxiangdong
     * @Description 创建流程申请
     * @Date 2019/9/27 9:36
     **/
    @Transactional
    public void createProcessApplication(ProcessApplicationRequest request, UserModel userByToken) {
        validateProcessApplication(request.getCaseId(), request.getFlowType(), request.getCaseType());
        ProcessApplication processApplication = generatePublicApplicationMessage(request, userByToken);
        processApplication.setFlowType(request.getFlowType());
        processApplicationRepository.save(processApplication);
    }

    /**
     * @Author wangxiangdong
     * @Description 验证是否存在未审批的申请
     * @Date 2019/10/10 15:56
     **/
    private void validateProcessApplication(String caseId, FlowType flowType, CaseType caseType) {
        Optional<CaseInfo> optional = caseInfoRepository.findById(caseId);
        if (!optional.isPresent()) {
            throw new BadRequestException(null, "caseInfo", "case.is.done");
        }
        CaseInfo caseInfo = optional.get();
        if (caseInfo.getCaseDataStatus().equals(CaseDataStatus.PAUSE)) {
            throw new BadRequestException(null, "caseInfo", "case.is.stop");
        }
        if (caseInfo.getCaseDataStatus().equals(CaseDataStatus.SETTLT) || caseInfo.getCaseDataStatus().equals(CaseDataStatus.REDUCE)) {
            throw new BadRequestException(null, "caseInfo", "case.is.clear");
        }
        //如果CaseType不一致，不能发起流程申请
        if (Objects.nonNull(caseType) && !caseType.equals(caseInfo.getCaseType())) {
            throw new BadRequestException(null, "caseInfo", "case.type.is.change");
        }
        if (Objects.equals(caseInfo.getPublicCaseFlag(),PublicCaseFlag.PUBLIC_CASE) && (!Objects.equals(FlowType.PUBLIC_DISTRIBUTE_CASE_APPLY,flowType))) {
            throw new BadRequestException(null, "caseInfo", "case.is.public");
        }
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        QProcessApplication processApplication = QProcessApplication.processApplication;
        booleanBuilder.and(processApplication.caseId.eq(caseId)).and(processApplication.flowType.eq(flowType)).and(processApplication.approvalStage.in(ApprovalStage.WAIT_APPROVAL, ApprovalStage.BEING_APPROVAL));
        //查看是否有未处理的流程申请
        boolean unHandleApply = processApplicationRepository.exists(booleanBuilder);
        if (unHandleApply) {
            throw new BadRequestException(null, "validateProcessApplication", "process.is.already.exist");
        }
        //如果案件为已留案 不能再继续申请留案
        if (Objects.equals(flowType, FlowType.LEAVE_CASE_APPLY) && Objects.equals(caseInfo.getLeaveFlag(), CaseLeaveFlag.HAS_LEAVE)) {
            throw new BadRequestException(null, "validateProcessApplication", "case.is.already.leave.case");
        }
        //如果案件已在流转案件池中，不能在继续发起流程申请
        if (Objects.equals(caseInfo.getCaseDataStatus(), CaseDataStatus.CIRCULATION)) {
            throw new BadRequestException(null, "validateProcessApplication", "case.is.already.in.circulation");
        }
        if(Objects.equals(FlowType.PUBLIC_CASE_APPLY,flowType)){
            if( Objects.equals(caseInfo.getPublicCaseFlag(), PublicCaseFlag.PUBLIC_CASE)){
                throw new BadRequestException(null, "validateProcessApplication", "case.is.already.in.public");
            }
            //公共案件申请 如存在未审批完成的流转申请，不能发起公共案件申请
            BooleanBuilder builder = new BooleanBuilder();
            builder.and(processApplication.caseId.eq(caseId)).and(processApplication.flowType.in(FlowType.VISIT_TO_TEL,FlowType.TEL_TO_VISIT)).and(processApplication.approvalStage.in(ApprovalStage.WAIT_APPROVAL, ApprovalStage.BEING_APPROVAL));
            boolean exists = processApplicationRepository.exists(builder);
            if(exists){
                throw  new BadRequestException(null,"validateProcessApplication","exists.circulation.unfinished.apply");
            }
            //如果存在未处理的协催申请，不能发起公共申请
            if(isExists(caseId,FlowType.VISIT_APPLY)){
                throw  new BadRequestException(null,"validateProcessApplication","exists.visit.unfinished.apply");
            }
            //如果存在协催，就不能申请公共案件、
            BooleanBuilder assistBuilder = new BooleanBuilder();
            assistBuilder.and(QAssistCase.assistCase.caseId.eq(caseId).and(QAssistCase.assistCase.assistStatus.in(AssistStatus.ASSIST_WAIT_ASSIGN,AssistStatus.ASSIST_COLLECTING)));
            if(assistCaseRepository.exists(assistBuilder)){
                throw  new BadRequestException(null,"validateProcessApplication", "assist.is.exsits");
            }
        }
        //如果存在未处理的公共案件申请，则不能申请协催
        if(Objects.equals(FlowType.VISIT_APPLY,flowType)){
            if(isExists(caseId,FlowType.PUBLIC_CASE_APPLY)){
                throw new BadRequestException(null, "validateProcessApplication", "exists.public.unfinished.apply");
            }
            //如存在未审批完成的流转申请，不能发起协催申请
            BooleanBuilder builder = new BooleanBuilder();
            builder.and(processApplication.caseId.eq(caseId)).and(processApplication.flowType.in(FlowType.VISIT_TO_TEL,FlowType.TEL_TO_VISIT)).and(processApplication.approvalStage.in(ApprovalStage.WAIT_APPROVAL, ApprovalStage.BEING_APPROVAL));
            boolean exists = processApplicationRepository.exists(builder);
            if(exists){
                throw new BadRequestException(null, "validateProcessApplication", "circulation.unfinished.apply.exsits");
            }
            //如果存在未处理公共申请，不能发起协催申请
            if(isExists(caseId,FlowType.PUBLIC_CASE_APPLY)){
                throw  new BadRequestException(null,"validateProcessApplication","public.unfinished.apply.exsits");
            }
        }
        if (Objects.equals(flowType, FlowType.VISIT_TO_TEL) || Objects.equals(flowType, FlowType.TEL_TO_VISIT)) {
            //检查是否有未处理的协催申请
            if (isExists(caseId,FlowType.VISIT_APPLY)) {
                throw new BadRequestException(null, "validateProcessApplication", "assist.or.apply.is.exists");
            }
            //检查是否有未完成的公共申请
            if(isExists(caseId,FlowType.PUBLIC_CASE_APPLY)){
                throw new BadRequestException(null, "validateProcessApplication", "exists.public.case.unfinished.apply");
            }
        }

    }

    /**
     * @Author wangxiangdong
     * @Description 查询是否存在未来处理完成的流程申请
     * @Date 2020/3/11 15:19
     **/
    private boolean isExists(String caseId,FlowType flowType){
        BooleanBuilder builder = new BooleanBuilder();
        QProcessApplication qProcessApplication = QProcessApplication.processApplication;
        builder.and(qProcessApplication.caseId.eq(caseId)).and(qProcessApplication.flowType.eq(flowType)).and(qProcessApplication.approvalStage.in(ApprovalStage.WAIT_APPROVAL, ApprovalStage.BEING_APPROVAL));
        return processApplicationRepository.exists(builder);
    }


    /**
     * @Author wangxiangdong
     * @Description 流程申请公共信息设置
     * @Date 2019/9/27 9:49
     **/
    private ProcessApplication generatePublicApplicationMessage(ProcessApplicationRequest processApplicationRequest, UserModel userByToken) {
        ProcessApplication processApplication = new ProcessApplication();
        CaseInfo caseInfo = caseInfoRepository.findById(processApplicationRequest.getCaseId()).orElseThrow(() -> new BadRequestException(null, "generatePublicApplicationMessage", "case.is.not.exists"));
        FlowConfiguration flowConfigByType = flowConfigurationService.findFlowConfigByType(processApplicationRequest.getFlowType());
        processApplication.setCaseId(caseInfo.getId());
        processApplication.setPersonalId(caseInfo.getPersonalId());
        processApplication.setPersonalName(caseInfo.getPersonalName());
        processApplication.setPrincipalId(caseInfo.getPrincipalId());
        processApplication.setPrincipalName(caseInfo.getPrincipalName());
        processApplication.setApplyDate(ZWDateUtil.getNowDateTime());
        processApplication.setBatchNumber(caseInfo.getBatchNumber());
        processApplication.setEndCaseDate(processApplicationRequest.getEndCaseDate());
        processApplication.setCertificateNo(caseInfo.getCertificateNo());
        processApplication.setApprovalStage(ApprovalStage.WAIT_APPROVAL);
        processApplication.setApplyContent(processApplicationRequest.getApplyContent());
        processApplication.setDerateAmount(processApplication.getDerateAmount());
        processApplication.setDerateRealAmount(processApplication.getDerateRealAmount());
        processApplication.setOperator(userByToken.getRealName());
        processApplication.setOperatorDate(ZWDateUtil.getNowDateTime());
        processApplication.setLeftAmt(caseInfo.getLeftAmt());
        processApplication.setOverdueAmtTotal(caseInfo.getOverdueAmtTotal());
        processApplication.setApplyId(userByToken.getId());
        processApplication.setCaseNumber(caseInfo.getCaseNumber());
        processApplication.setApplyName(userByToken.getRealName());
        if (Objects.nonNull(processApplicationRequest.getFileIds())) {
            processApplication.setFileId(processApplicationRequest.getFileIds().stream().collect(Collectors.joining(",")));
        }
        processApplication.setDerateAmount(processApplicationRequest.getApplyAmount());
        processApplication.setApplyRemark(processApplicationRequest.getApplyRemark());
        processApplication.setPersonalAddressId(processApplicationRequest.getPersonalAddressId());
        processApplication.setPersonalContactId(processApplication.getPersonalContactId());
        processApplication.setVisitTimeStart(processApplicationRequest.getVisitTimeStart());
        processApplication.setVisitTimeEnd(processApplicationRequest.getVisitTimeEnd());
        processApplication.setAddressDetail(processApplicationRequest.getAddressDetail());
        processApplication.setAddressType(processApplicationRequest.getAddressType());
        processApplication.setRelation(processApplicationRequest.getRelationShip());
        processApplication.setCollectorId(caseInfo.getCurrentCollector().getId());
        processApplication.setCollectorName(caseInfo.getCurrentCollector().getRealName());
        processApplication.setLetterTempId(processApplicationRequest.getLetterTemp());
        Set<ProcessFlowNode> processFlowNodes = new HashSet<>();
        setupFlowNodeSteps(processFlowNodes,flowConfigByType.getFlowNode(),processApplicationRequest.getFlowType(),userByToken.getRealName());
        processApplication.setProcessFlowNodes(processFlowNodes);
        return processApplication;
    }

    /**
     * @Author wangxiangdong
     * @Description  申请通过后，设置流程审批节点
     * @Date 2020/3/24 10:22
     **/
    private void setupFlowNodeSteps(Set<ProcessFlowNode> processFlowNodes,Set<FlowNodeConfig> flowNodeConfigSet,FlowType flowType,String realName){
        //设置流程节点
        flowNodeConfigSet.forEach(flowNodeConfig -> {
            ProcessFlowNode processFlowNode = new ProcessFlowNode();
            processFlowNode.setNodeValue(flowNodeConfig.getNodeValue());
            processFlowNode.setApprovalStatus(ApprovalStatus.WAIT_APPROVAL);
            Set<ProcessApprover> processApprovers = new HashSet<>();
            //设置审批人信息
            flowNodeConfig.getApproverConfigs().forEach(approverConfig -> {
                ProcessApprover processApprover = new ProcessApprover();
                BeanUtils.copyPropertiesIgnoreNull(approverConfig, processApprover);
                processApprover.setId(null);
                processApprovers.add(processApprover);
            });
            processFlowNode.setProcessApprovers(processApprovers);
            processFlowNodes.add(processFlowNode);
        });
        //设置流程审批第一步节点
        ProcessFlowNode processFlowNode = processFlowNodes.stream().min(Comparator.comparing(ProcessFlowNode::getNodeValue))
                .orElseThrow(() -> new BadRequestException(null, "generatePublicApplicationMessage", "node.is.not.found"));
        processFlowNode.setIsShow(BaseSelect.YES);
        List<String> approveList = processFlowNode.getProcessApprovers().stream().map(ProcessApprover::getUserId).collect(Collectors.toList());
        sendApproveReminderMessage(flowType, realName, approveList);
        //设置结束节点
        processFlowNodes.stream().max(Comparator.comparing(ProcessFlowNode::getNodeValue))
                .orElseThrow(() -> new BadRequestException(null, "generatePublicApplicationMessage", "node.is.not.found")).setIsEnd(BaseSelect.YES);
    }

    /**
     * @Author wangxiangdong
     * @Description 流程审批
     * @Date 2019/9/28 10:39
     **/
    @Transactional
    public void processApprove(ApproveRequest request, UserModel userByToken) {
        ProcessApplication processApplication = processApplicationRepository.findById(request.getProcessApplicationId()).orElseThrow(() -> new BadRequestException(null, "", "application.is.not.found"));
        ProcessFlowNode currentFlowNode = processApplication.getProcessFlowNodes().stream().filter(processFlowNode -> Objects.equals(processFlowNode.getId(), request.getProcessFlowNodeId()))
                .collect(Collectors.toList()).get(0);
        if (Objects.equals(request.getApprovalResult(), ApprovalResult.APPROVED_REJECT)) {
            currentFlowNode.setApprovedResult(ApprovalResult.APPROVED_REJECT);
            setProcessApplication(processApplication, ApprovalResult.APPROVED_REJECT);
            sendApproverResultMessage(request.getFlowType(), request.getApprovalResult(), processApplication.getApplyId(), processApplication.getPersonalName());
        } else {
            currentFlowNode.setApprovedResult(request.getApprovalResult());
            if (Objects.equals(currentFlowNode.getIsEnd(), BaseSelect.YES)) {
                setProcessApplication(processApplication, ApprovalResult.APPROVED_PASS);
                switch (request.getFlowType()){
                    case LEAVE_CASE_APPLY:
                        executeLeaveCase(request.getCaseId(), processApplication.getEndCaseDate());
                        break;
                    case PUBLIC_CASE_APPLY:
                        executePublicCase(request.getCaseId());
                        break;
                    case PUBLIC_DISTRIBUTE_CASE_APPLY:
                        executePublicCaseDistribute(processApplication, request.getCaseId());
                        break;
                    case VISIT_APPLY:
                        executeGenerateAssistCase(processApplication, request.getCaseId(), userByToken);
                        break;
                    case TEL_TO_VISIT :
                        executeTurnCase(request.getCaseId(), request.getFlowType());
                        break;
                    case VISIT_TO_TEL:
                        executeTurnCase(request.getCaseId(), request.getFlowType());
                        break;
                    default:
                        throw  new BadRequestException(null,"processApprove","flow.type.is.unidentified");
                }
                sendApproverResultMessage(request.getFlowType(), request.getApprovalResult(), processApplication.getApplyId(), processApplication.getPersonalName());
            } else {
                processApplication.setApprovalStage(ApprovalStage.BEING_APPROVAL);
                setNextApprover(processApplication, currentFlowNode.getNodeValue());
            }
        }
        currentFlowNode.setApprovalStatus(ApprovalStatus.APPROVED_COMPLETED);
        currentFlowNode.setApprovalTime(ZWDateUtil.getNowDateTime());
        currentFlowNode.setRemark(request.getApproveRemark());
        currentFlowNode.setApprovedResult(request.getApprovalResult());
        processApplicationRepository.save(processApplication);
    }

    /**
     * @Author wangxiangdong
     * @Description 案件类型流转处理
     * @Date 2020/1/7 16:40
     **/
    private void executeTurnCase(String caseId, FlowType flowType) {
        CaseInfo caseInfo = caseInfoRepository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executeLeaveCase", "case.is.not.exists"));
        if (Objects.equals(flowType, FlowType.TEL_TO_VISIT)) {
            caseInfo.setCaseType(CaseType.VISIT_CASE);
        } else {
            caseInfo.setCaseType(CaseType.TEL_CASE);
        }
        User collector = caseInfo.getCurrentCollector();
        if (Objects.nonNull(collector)) {
            caseInfo.setDepartment(collector.getDepartment());
            caseInfo.setCurrentCollector(null);
        }
        caseInfo.setCaseDataStatus(CaseDataStatus.CIRCULATION);
        //结束协催
        List<AssistCase> assistCaseList = Lists.newArrayList(assistCaseRepository.findAll(QAssistCase.assistCase.caseId.eq(caseId).and(QAssistCase.assistCase.assistStatus.in(AssistStatus.ASSIST_WAIT_ASSIGN, AssistStatus.ASSIST_COLLECTING))));
        for (AssistCase assistCase : assistCaseList){
            assistCase.setAssistStatus(AssistStatus.ASSIST_CANCEL);
        }
        if(!assistCaseList.isEmpty()){
            assistCaseRepository.saveAll(assistCaseList);
        }
        caseInfo.setIsAssist(BaseSelect.NO);
        caseInfoRepository.save(caseInfo);
    }

    /**
     * @Author wangxiangdong
     * @Description 审批提醒
     * @Date 2019/10/16 15:39
     **/
    private void sendApproveReminderMessage(FlowType flowType, String applyName, List<String> approverIds) {
        switch (flowType) {
            case PUBLIC_CASE_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "公共案件申请审批", "您收到一条来自" + applyName + "的公共案件申请,请及时审批", approverIds);
                break;
            case PUBLIC_DISTRIBUTE_CASE_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "公共案件分配申请审批", "您收到一条来自" + applyName + "的公共案件分配申请,请及时审批", approverIds);
                break;
            case LEAVE_CASE_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "留案申请审批", "您收到一条来自" + applyName + "的留案申请,请及时审批", approverIds);
                break;
            case CHECK_MATERIAL_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "资料申请审批", "您收到一条来自" + applyName + "的资料申请,请及时审批", approverIds);
                break;
            case REPORT_CASE_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "报案申请审批", "您收到一条来自" + applyName + "的报案申请,请及时审批", approverIds);
                break;
            case DERATE_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "减免申请审批", "您收到一条来自" + applyName + "的减免申请,请及时审批", approverIds);
                break;
            case VISIT_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "外访申请审批", "您收到一条来自" + applyName + "的外访申请,请及时审批", approverIds);
                break;
            case LETTER_PRINT_APPLY:
                baseService.sendMessageToMany(MessageType.APPLY_APPROVE_MSG, "信函打印申请审批", "您收到一条来自" + applyName + "的信函打印申请,请及时审批", approverIds);
                break;
            default:
                break;
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 发送审批结果消息
     * @Date 2019/10/16 15:39
     **/
    private void sendApproverResultMessage(FlowType flowType, ApprovalResult approvalResult, String applyId, String personalName) {
        String approveResultStr;
        if (Objects.equals(ApprovalResult.APPROVED_PASS, approvalResult)) {
            approveResultStr = "已通过";
        } else {
            approveResultStr = "已拒绝";
        }
        switch (flowType) {
            case PUBLIC_CASE_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "公共案件申请审批结果", "客户:" + personalName + "的公共案件申请审批" + approveResultStr, applyId);
                break;
            case PUBLIC_DISTRIBUTE_CASE_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "公共案件分配申请审批结果", "客户:" + personalName + "的公共案件分配申请审批" + approveResultStr, applyId);
                break;
            case LEAVE_CASE_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "留案申请审批结果", "客户:" + personalName + "的留案案件申请审批" + approveResultStr, applyId);
                break;
            case CHECK_MATERIAL_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "资料申请审批结果", "客户:" + personalName + "的资料申请审批" + approveResultStr, applyId);
                break;
            case REPORT_CASE_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "报案申请审批结果", "客户:" + personalName + "的报案申请审批" + approveResultStr, applyId);
                break;
            case DERATE_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "减免申请审批结果", "客户:" + personalName + "的减免申请审批" + approveResultStr, applyId);
                break;
            case VISIT_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "外访申请审批结果", "客户:" + personalName + "的外访申请审批" + approveResultStr, applyId);
                break;
            case LETTER_PRINT_APPLY:
                baseService.sendMessageToOne(MessageType.APPLY_APPROVE_MSG, "信函打印申请审批结果", "客户:" + personalName + "的信函打印申请审批" + approveResultStr, applyId);
                break;
            default:
                break;
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 协催审批通过 生成协催案件
     * @Date 2019/10/11 14:47
     **/
    private void executeGenerateAssistCase(ProcessApplication processApplication, String caseId, UserModel userByToken) {
        CaseInfo caseInfo = caseInfoRepository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executePublicCaseDistribute", "case.is.not.exists"));
        User user = userRepository.findById(processApplication.getCollectorId()).orElseThrow(() -> new BadRequestException(null, "user", "user.is.null"));
        AssistCase assistCase = new AssistCase();
        assistCase.setCaseId(caseInfo.getId());
        assistCase.setCaseNumber(caseInfo.getCaseNumber());
        assistCase.setSex(caseInfo.getSex());
        assistCase.setPhone(caseInfo.getPhone());
        assistCase.setAddressDetail(processApplication.getAddressDetail());
        assistCase.setAddressType(processApplication.getAddressType());
        assistCase.setApplyRealName(processApplication.getApplyName());
        assistCase.setApplyReason(processApplication.getApplyRemark());
        assistCase.setAssistStatus(AssistStatus.ASSIST_WAIT_ASSIGN);
        assistCase.setBatchNumber(caseInfo.getBatchNumber());
        assistCase.setCardNo(caseInfo.getCardNo());
        assistCase.setCertificateNo(caseInfo.getCertificateNo());
        assistCase.setCollectionRecordCount(caseInfo.getCollectionRecordCount());
        assistCase.setCollectorDepartmentName(user.getDepartment().getName());
        assistCase.setCurrentCollector(user.getRealName());
        assistCase.setLatestPayAmt(caseInfo.getLatestPayAmt());
        assistCase.setLeftAmt(caseInfo.getLeftAmt());
        assistCase.setOperator(userByToken.getRealName());
        assistCase.setOperatorTime(ZWDateUtil.getNowDateTime());
        assistCase.setOverdueAmtTotal(caseInfo.getOverdueAmtTotal());
        assistCase.setOverdueDays(caseInfo.getOverdueDays());
        assistCase.setOverduePeriods(caseInfo.getOverduePeriods());
        assistCase.setLatestPayDate(caseInfo.getLatestPayDate());
        assistCase.setVisitTimeStart(processApplication.getVisitTimeStart());
        assistCase.setVisitTimeEnd(processApplication.getVisitTimeEnd());
        assistCase.setRelation(processApplication.getRelation());
        assistCase.setPrincipalName(caseInfo.getPrincipalName());
        assistCase.setPrincipalId(caseInfo.getPrincipalId());
        assistCase.setPersonalName(caseInfo.getPersonalName());
        assistCase.setPersonalId(caseInfo.getPersonalId());
        assistCase.setPersonalAddressId(processApplication.getPersonalAddressId());
        assistCase.setPersonalContactId(processApplication.getPersonalContactId());
        assistCaseRepository.save(assistCase);
    }

    /**
     * @Author wangxiangdong
     * @Description 公共案件
     * @Date 2019/10/9 18:11
     **/
    private void executePublicCaseDistribute(ProcessApplication processApplication, String caseId) {
        CaseInfo caseInfo = caseInfoRepository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executePublicCaseDistribute", "case.is.not.exists"));
        User user = userRepository.findById(processApplication.getApplyId()).orElseThrow(() -> new BadRequestException(null, "user", "user.is.null"));
        caseInfo.setCaseDataStatus(CaseDataStatus.IN_POOL);
        caseInfo.setPublicCaseFlag(PublicCaseFlag.NO_PUBLIC_CASE);
        caseInfo.setTransferDate(ZWDateUtil.getNowDateTime());
        String outUserId = caseInfo.getCurrentCollector().getId();
        caseInfo.setCurrentCollector(user);
        CaseTransferLog caseTransferLog = new CaseTransferLog();
        caseTransferLog.setCaseId(caseId);
        caseTransferLog.setOutUserId(outUserId);
        caseTransferLog.setInUserId(user.getId());
        caseTransferLog.setOperContent("案件流转:".concat(user.getRealName()));
        caseTransferLog.setUserName(processApplication.getApplyId());
        caseTransferLog.setFullName(processApplication.getApplyName());
        caseTransferLog.setOperatorTime(ZWDateUtil.getNowDateTime());
        caseTransferLogRepository.save(caseTransferLog);
        caseInfoRepository.save(caseInfo);
    }

    /**
     * @Author wangxiangdong
     * @Description 审批通过  案件进入公共案件池
     * @Date 2019/10/9 18:11
     **/
    private void executePublicCase(String caseId) {
        CaseInfo caseInfo = caseInfoRepository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executePublicCase", "case.is.not.exists"));
        caseInfo.setPublicCaseFlag(PublicCaseFlag.PUBLIC_CASE);
        caseInfoRepository.save(caseInfo);
    }

    /**
     * @Author wangxiangdong
     * @Description 审批通过 留案操作
     * @Date 2019/9/28 14:20
     **/
    private void executeLeaveCase(String caseId, Date endCaseDate) {
        CaseInfo caseInfo = caseInfoRepository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executeLeaveCase", "case.is.not.exists"));
        caseInfo.setLeaveFlag(CaseLeaveFlag.HAS_LEAVE);
        caseInfo.setEndCaseDate(endCaseDate);
        BaseCase baseCase = baseCaseRespository.findById(caseId).orElseThrow(() -> new BadRequestException(null, "executeLeaveCase", "case.is.not.exists"));
        baseCase.setEndCaseDate(endCaseDate);
        caseInfoRepository.save(caseInfo);
        baseCaseRespository.save(baseCase);
    }

    /**
     * @Author wangxiangdong
     * @Description 设置流程申请信息
     * @Date 2019/9/28 11:07
     **/
    private void setProcessApplication(ProcessApplication processApplication, ApprovalResult approvalResult) {
        if (Objects.equals(approvalResult.name(), ApprovalResult.APPROVED_PASS.name())) {
            processApplication.setApprovalStage(ApprovalStage.APPROVED_PASS);
        } else {
            processApplication.setApprovalStage(ApprovalStage.APPROVED_REJECT);
        }
    }

    /**
     * @Author wangxiangdong
     * @Description 设置下一审批节点
     * @Date 2019/9/28 10:55
     **/
    private void setNextApprover(ProcessApplication processApplication, Integer nodeValue) {
        ProcessFlowNode nextFlowNode = processApplication.getProcessFlowNodes().stream().filter(processFlowNode -> processFlowNode.getNodeValue() == Integer.sum(nodeValue, 1)).
                collect(Collectors.toList()).get(0);
        nextFlowNode.setIsShow(BaseSelect.YES);
        List<String> approveList = nextFlowNode.getProcessApprovers().stream().map(ProcessApprover::getUserId).collect(Collectors.toList());
        sendApproveReminderMessage(processApplication.getFlowType(), processApplication.getApplyName(), approveList);
    }

    public Page<ProcessApplicationResponse> getProcessApplicationByFlowType(ProcessApplcationRequest processApplcationRequest, Pageable pageable) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (Objects.equals(processApplcationRequest.getFlowType(), FlowType.VISIT_APPLY)) {
            booleanBuilder.and(QProcessApplication.processApplication.flowType.eq(processApplcationRequest.getFlowType()))
                    .or(QProcessApplication.processApplication.flowType.eq(FlowType.LETTER_PRINT_APPLY));
        } else if (Objects.equals(processApplcationRequest.getFlowType(), FlowType.TEL_TO_VISIT)) {
            booleanBuilder.and(QProcessApplication.processApplication.flowType.eq(processApplcationRequest.getFlowType()))
                    .or(QProcessApplication.processApplication.flowType.eq(FlowType.VISIT_TO_TEL));
        } else {
            booleanBuilder.and(QProcessApplication.processApplication.flowType.eq(processApplcationRequest.getFlowType()));
        }
        booleanBuilder.and(QProcessApplication.processApplication.caseId.eq(processApplcationRequest.getCaseId()));
        return (processApplicationRepository.findAll(booleanBuilder, pageable).map(processApplication -> modelMapper.map(processApplication, ProcessApplicationResponse.class)));
    }

    /**
     * @Author wangxiangdong
     * @Description 批量审批
     * @Date 2019/10/14 9:47
     **/
    public void approveByBatch(ApproveByBatchModel approveByBatchModel, UserModel userByToken) {
        List<ApproveRequest> approveRequestList = approveByBatchModel.getApproveRequestList();
        approveRequestList.forEach(approveRequest -> {
            processApprove(approveRequest, userByToken);
        });
    }

    /**
     * @Author wangxiangdong
     * @Description 更改信函打印状态
     * @Date 2019/10/15 10:56
     **/
    public void changePrintStatus(ChangePrintStatusRequest changePrintStatusRequest) {
        List<ProcessApplication> processApplicationList = processApplicationRepository.findAllById(changePrintStatusRequest.getProcessApplicationIds());
        if (!processApplicationList.isEmpty()) {
            processApplicationList.forEach(processApplication -> {
                processApplication.setExportState(ExportState.EXPORTED);
            });
        }
        processApplicationRepository.saveAll(processApplicationList);
    }

}
